package com.ruoyi.smartai.utils;

import com.ruoyi.common.constant.CustomerPersonaAgents;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.smartai.entity.SimilarityRequest;
import com.ruoyi.smartai.entity.SimilarityResponse;

import com.ruoyi.system.domain.SysOperLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryPolicy;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.listener.RetryListenerSupport;
import org.springframework.retry.policy.CompositeRetryPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.policy.TimeoutRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.netty.http.client.HttpClient;


/**
 * whatsapp消息工具
 */
@Component
public class WhatsAPPUtils {

    // Redis key前缀
    public static final String MESSAGE_KEY_PREFIX = "message:content:";
    public static final String TIMESTAMP_KEY_PREFIX = "message:timestamp:";
    public static final String COUNT_KEY_PREFIX = "message:count:";

    public static final String FANS_MESSAGE_PREFIX = "message:fans:";

    //合并规定时间内的内容
    public static final int MESSAGE_COMBINE_SECONDS = 15;

    private static final Logger log = LoggerFactory.getLogger(WhatsAPPUtils.class);
    private static final RestTemplate restTemplate = restTemplate();

    /**
     * 发送whatsapp消息
     */
    public static String sendMessage(String url, String fromNumber, String toNumber, String messageType, String message, String chatId) {
        RetryTemplate retryTemplate = createRetryTemplate();
        try {
            return retryTemplate.execute(context -> {
                // 构建请求体
                Map<String, String> body = new HashMap<>();
                body.put("id", fromNumber);
                body.put("number", toNumber + "@c.us");
                body.put("messageType", messageType);
                body.put("from", "1");
                body.put("chatId", chatId);
                body.put("messageText", getmeidaURL(message));
                log.info("发送的地址是：" + url);
                log.info("发送的消息是：" + message);
                if (StringUtils.isNotEmpty(message)) {
                    // 发送 POST 请求
                    restTemplate.postForEntity(url, body, String.class);
                }
                return message;
            });
        } catch (Exception e) {
            log.error("sendMessage 错误:" + e);
        }
        return null;
    }

    private static String getmeidaURL(String message) {
        // 判断是否是以图片或视频的后缀为结尾,如果是把/prod-api替换成/home/data
        if (message == null || message.isEmpty()) {
            return message;
        }

        // 定义常见的图片和视频文件后缀
        String[] mediaExtensions = {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp",
                ".mp4", ".avi", ".mov", ".wmv", ".flv", ".mkv"};

        // 检查消息是否以媒体文件后缀结尾（不区分大小写）
        boolean isMediaFile = false;
        String lowerCaseMessage = message.toLowerCase();
        for (String ext : mediaExtensions) {
            if (lowerCaseMessage.endsWith(ext)) {
                isMediaFile = true;
                break;
            }
        }

        // 如果是媒体文件，替换路径前缀
        if (isMediaFile && message.contains("/prod-api")) {
            return message.replace("/prod-api", "/home/data");
        }

        return message;
    }

    /**
     * 检查并存储消息
     *
     * @param customerNumber 客户编号
     * @param message        消息内容
     * @return true: 消息未被重复发送；false: 消息已重复发送
     */
    public static boolean checkAndStoreMessage(String customerNumber, String message, String messageType) {
        // 构建 Redis 的键，格式为 "customer:customerNumber:messageContent"
        String key = "customer:" + customerNumber + ":" + message;
        RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
        if (messageType.equals("0")) {
            if (message.length() > 10) {
                // 检查 Redis 中是否存在该键
                if (redisCache.hasKey(key)) {
                    // 如果存在，说明在一小时内已经发送过相同的消息
                    return true;
                } else {
                    // 如果不存在，则将消息存储到 Redis 中，并设置过期时间为 1 小时
                    redisCache.setCacheObject(key, message, 1, TimeUnit.HOURS);
                    return false;
                }
            } else {
                return false;
            }
        } else {
            if (redisCache.hasKey(key)) {
                // 如果存在，说明在一小时内已经发送过相同的消息
                return true;
            } else {
                // 如果不存在，则将消息存储到 Redis 中，并设置过期时间为 1 小时
                redisCache.setCacheObject(key, message);
                return false;
            }
        }
    }

    /**
     * 发送whatsapp消息
     */
    public static String sendMessage(String url, String fromNumber, String toNumber, String messageType, String message, String chatId, boolean isTran) {
        try {
            if (isTran) {
                log.info("需要翻译的内容是：" + message);
                if (message.length() > 0) {
                    // 解码URL编码的内容
                    try {
                        String tranMessage = translateByNumber(toNumber, message);
                        tranMessage = java.net.URLDecoder.decode(tranMessage, "UTF-8");
                        message = tranMessage;
                    } catch (UnsupportedEncodingException e) {
                        log.error("解码翻译内容失败: " + e.getMessage());
                    }
                    log.info("翻译后的内容是：" + message);
                }
            }
        } catch (Exception e) {

        }
        return sendMessage(url, fromNumber, toNumber, messageType, message, chatId);
    }

    public static String getTrans(String toNumber, String message, boolean isTran) {
        try {
            if (isTran) {
                log.info("需要翻译的内容是：" + message);
                if (message.length() > 0) {
                    // 解码URL编码的内容
                    try {
                        String tranMessage = translateByNumber(toNumber, message);
                        tranMessage = java.net.URLDecoder.decode(tranMessage, "UTF-8");
                        message = tranMessage;
                    } catch (UnsupportedEncodingException e) {
                        log.error("解码翻译内容失败: " + e.getMessage());
                    }
                    log.info("翻译后的内容是：" + message);
                }
            }
        } catch (Exception e) {

        }
        return message;
    }


    private void pullPicIntent(String customer, String message) {
        RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
        String keys = "persona:customer:" + customer + ":agents";
        CustomerPersonaAgents agent = redisCache.getCacheObject(keys);
        String characterImage = agent.getCharacterImage();
        if (StringUtils.isNotNull(characterImage)) {
            String picIntent = redisCache.getCacheObject("smart:utils:picintent");
            String intentPrompt = redisCache.getCacheObject(picIntent);
            String[] imagesText = characterImage.split("\n");
            StringBuilder images = new StringBuilder();
            for (String text : imagesText) {
                if (text.contains(":")) {
                    String[] pic = text.split(":");
                    images.append(pic[0]);
                }
            }
            intentPrompt.replace("{piclistt}", images.toString());
        }
    }


    /**
     * 根据号码区号自动翻译
     *
     * @param toNumber
     * @param message
     * @return
     */
    public static String translateByNumber(String toNumber, String message) {
        try {
            if (message.length() < 1) {
                return message;
            }
            Environment env = SpringUtils.getBean(Environment.class);
            String url = env.getProperty("apiSevicePath.translateByNumber");
            // 构建完整URL
            String fullUrl = url + "?text=" + message + "&number=" + toNumber;

            ResponseEntity<String> response = restTemplate.getForEntity(fullUrl, String.class);
//            log.info("translateByNumber:" + response.toString() + "  " + toNumber);
            String body = response.getBody();
            // 如果返回的字符串被双引号包围，则移除这些引号
            if (body != null && body.startsWith("\"") && body.endsWith("\"")) {
                body = body.substring(1, body.length() - 1);
            }
            return body;
        } catch (Exception e) {
            log.error("translateByNumber 错误:" + e);
        }
        return message;
    }


    /**
     * 根据目标语言翻译
     *
     * @param target
     * @param message
     * @return
     */
    public static String translateByTarget(String target, String message) {
        try {
            Environment env = SpringUtils.getBean(Environment.class);
            String url = env.getProperty("apiSevicePath.translateByTarget");
            // 构建完整URL
            String fullUrl = url + "?text=" + message + "&target=" + target;

            ResponseEntity<String> response = restTemplate.getForEntity(fullUrl, String.class);
//            log.info("translateByTarget:" + response.toString() + "  " + target);
            String body = response.getBody();
            // 如果返回的字符串被双引号包围，则移除这些引号
            if (body != null && body.startsWith("\"") && body.endsWith("\"")) {
                body = body.substring(1, body.length() - 1);
            }
            // 对 body 进行 URL 解码
            if (body != null) {
                body = URLDecoder.decode(body, StandardCharsets.UTF_8.name());
            }
            return body;
        } catch (Exception e) {
            log.error("translateByTarget 错误:" + e);
            return null;
        }
    }

//    /**
//     * 获取ai会话信息
//     */
//    public static String getChatByAI(String message, String customer_number, String fansId) {
//        try {
//            Environment env = SpringUtils.getBean(Environment.class);
//            String url = env.getProperty("apiSevicePath.chat_reply");
//            // 构建完整URL
//            String fullUrl = url + "?content=" + message + "&customer_number=" + customer_number + "&fansId=" + fansId;
//
//            ResponseEntity<String> response = restTemplate.getForEntity(fullUrl, String.class);
//            String body = response.getBody();
//            // 如果返回的字符串被双引号包围，则移除这些引号
//            if (body != null && body.startsWith("\"") && body.endsWith("\"")) {
//                body = body.substring(1, body.length() - 1);
//            }
//            log.info("getChatByAI body:" + body);
//            return body;
//        } catch (Exception e) {
//            log.error("translateByNumber 错误:" + e);
//        }
//        return message;
//    }


    /**
     * 获取历史聊天记录
     */


    /**
     * 发送whatsapp消息
     */
    public static SimilarityResponse getSimilarScenario(String url, SimilarityRequest request) {
        // 创建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 创建请求实体
        HttpEntity<SimilarityRequest> requestEntity = new HttpEntity<>(request, headers);

        try {
            // 使用exchange方法发送请求
            ResponseEntity<SimilarityResponse> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, SimilarityResponse.class);

            // 检查状态码
            if (response.getStatusCode().is2xxSuccessful()) {
                return response.getBody();
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }
    }

//    /**
//     * 获取用户回复的意图
//     */
//    public static String getReplyIntent(String message, String customer_number, String fansId) {
//        try {
//            Environment env = SpringUtils.getBean(Environment.class);
//            String url = env.getProperty("apiSevicePath.chat_reply");
//            // 构建完整URL
//            String fullUrl = url + "?content=" + message + "&customer_number=" + customer_number + "&fansId=" + fansId;
//
//            ResponseEntity<String> response = restTemplate.getForEntity(fullUrl, String.class);
//            String body = response.getBody();
//            // 如果返回的字符串被双引号包围，则移除这些引号
//            if (body != null && body.startsWith("\"") && body.endsWith("\"")) {
//                body = body.substring(1, body.length() - 1);
//            }
//            log.info("getReplyIntent body:" + body);
//            return body;
//        } catch (Exception e) {
//            log.error("translateByNumber 错误:" + e);
//        }
//        return message;
//    }

    /**
     * 获取用户回复的意图
     */
//    @Retryable(
//            value = {Exception.class}, // 指定需要重试的异常类型
//            maxAttempts = 3, // 最大重试次数
//            backoff = @Backoff(delay = 2000) // 重试间隔时间，单位为毫秒
//    )
    public static String getChatIntent(String message, String fansId) {
        RetryTemplate retryTemplate = createRetryTemplate();
        try {
            return retryTemplate.execute(context -> {
                Environment env = SpringUtils.getBean(Environment.class);
                String url = env.getProperty("apiSevicePath.chat_intent");

                // 创建设置了超时的临时 RestTemplate
                RestTemplate tempRestTemplate = new RestTemplate();

                // 设置超时参数
                SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
                factory.setConnectTimeout(30000);  // 连接超时30秒
                factory.setReadTimeout(50000);     // 读取超时50秒
                tempRestTemplate.setRequestFactory(factory);

                // 创建请求头
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);

                // 创建请求体 - 使用Map或专用类
                Map<String, String> requestBody = new HashMap<>();
                requestBody.put("content", message);
                requestBody.put("fansId", fansId);

                // 创建HTTP实体
                HttpEntity<Map<String, String>> entity = new HttpEntity<>(requestBody, headers);

                // 发送POST请求
                ResponseEntity<String> response = tempRestTemplate.postForEntity(url, entity, String.class);

                if (response == null) {
                    log.warn("Received null response, triggering retry");
                    throw new Exception("Response body is empty");
                }
                String body = response.getBody();
                if (body != null && body.startsWith("\"") && body.endsWith("\"")) {
                    body = body.substring(1, body.length() - 1);
                }
                if (StringUtils.isNull(body)) {
                    log.warn("Received empty body, triggering retry");
                    throw new Exception("Response body is empty");
                }
                log.info("getChatIntent body:" + body);
                return body;
            });
        } catch (Exception e) {
            log.error("getChatIntent 错误:" + e);
        }
        return null;
    }

    // 配置RestTemplate
    public static RestTemplate restTemplate() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(180000); // 连接超时3分钟
        factory.setReadTimeout(180000);    // 读取超时3分钟
        return new RestTemplate(factory);
    }

    private static RetryTemplate createRetryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();

        // 创建组合重试策略
        CompositeRetryPolicy compositeRetryPolicy = new CompositeRetryPolicy();

        // 设置基本重试策略 - 增加重试次数和延长超时时间
        SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy(5, // 增加到5次重试
                Collections.singletonMap(Exception.class, true));

        // 设置超时重试策略 - 延长总体超时时间
        TimeoutRetryPolicy timeoutPolicy = new TimeoutRetryPolicy();
        timeoutPolicy.setTimeout(120000L); // 延长到120秒，确保有足够的重试时间

        // 组合多个重试策略
        compositeRetryPolicy.setPolicies(new RetryPolicy[]{
                simpleRetryPolicy,
                timeoutPolicy
        });

        // 设置组合重试策略
        retryTemplate.setRetryPolicy(compositeRetryPolicy);

        // 调整退避策略的参数
        ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
        backOffPolicy.setInitialInterval(2000); // 初始间隔2秒
        backOffPolicy.setMultiplier(2.0);       // 每次间隔2倍增长
        backOffPolicy.setMaxInterval(60000);    // 最大间隔20秒

        retryTemplate.setBackOffPolicy(backOffPolicy);

        // 设置重试监听器
        retryTemplate.registerListener(new RetryListenerSupport() {
            @Override
            public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
                log.warn("重试失败 - 尝试次数: {}, 异常: {}", context.getRetryCount(), throwable.getMessage());
            }
        });

        return retryTemplate;
    }

    /**
     * 延时发送
     *
     * @param startTime
     * @param endTime
     */
    public static void randomThread(int startTime, int endTime) {
        try {
            // 生成随机延时时间：5到5+delayTime秒之间
            long randomDelay = startTime * 1000 + (long) (Math.random() * Long.valueOf(endTime) * 1000);
            // 延时等待
            Thread.sleep(randomDelay);
        } catch (Exception e) {

        }
    }

    /**
     * 获取fans的key
     *
     * @param contactNumber
     * @param fansId
     * @return
     */
    public static String getFansDiodlogKey(String contactNumber, String fansId) {
        return WhatsAPPUtils.FANS_MESSAGE_PREFIX + contactNumber + ":" + fansId;
    }


    public static String getWeather(String contactNumber) {
        try {
            RetryTemplate retryTemplate = createRetryTemplate();
            return retryTemplate.execute(context -> {
                Environment env = SpringUtils.getBean(Environment.class);
                String url = env.getProperty("apiSevicePath.weather_url");
                // 构建完整URL
                String fullUrl = url + "?curtomer=" + contactNumber;

                ResponseEntity<String> response = restTemplate.getForEntity(fullUrl, String.class);
                if (response == null) {
                    log.warn("Received null response, triggering retry");
                    throw new Exception("Response body is empty");
                }
                String body = response.getBody();
                // 如果返回的字符串被双引号包围，则移除这些引号
                if (body != null && body.startsWith("\"") && body.endsWith("\"")) {
                    body = body.substring(1, body.length() - 1);
                }
                // 检查 body 是否为空字符串
                if (StringUtils.isNull(body)) {
                    log.warn("Received empty body, triggering retry");
                    throw new Exception("Response body is empty");
                }
                log.info("getWeather body:" + body);
                return body;
            });
        } catch (Exception e) {
            log.error("getWeather 错误:" + e);
        }
        return null;
    }


    //    @Retryable(
//            value = {Exception.class}, // 指定需要重试的异常类型
//            maxAttempts = 3, // 最大重试次数
//            backoff = @Backoff(delay = 2000) // 重试间隔时间，单位为毫秒
//    )
    public static String getCityTime(String contactNumber) {
        try {
            RetryTemplate retryTemplate = createRetryTemplate();
            return retryTemplate.execute(context -> {
                Environment env = SpringUtils.getBean(Environment.class);
                String url = env.getProperty("apiSevicePath.city_time");
                // 构建完整URL
                String fullUrl = url + "?curtomer=" + contactNumber;

                ResponseEntity<String> response = restTemplate.getForEntity(fullUrl, String.class);
                if (response == null) {
                    log.warn("Received null response, triggering retry");
                    throw new Exception("Response body is empty");
                }
                String body = response.getBody();
                // 如果返回的字符串被双引号包围，则移除这些引号
                if (body != null && body.startsWith("\"") && body.endsWith("\"")) {
                    body = body.substring(1, body.length() - 1);
                }
                // 检查 body 是否为空字符串
                if (StringUtils.isNull(body)) {
                    log.warn("Received empty body, triggering retry");
                    throw new Exception("Response body is empty");
                }
                log.info("getCityTime body:" + body);
                return body;
            });
        } catch (Exception e) {
            log.error("getCityTime 错误:" + e);
        }
        return null;
    }


    public static String getImagePath(String scenesId, String contactNumber, int item) {
        return "/home/data/image/" + scenesId + "/" + contactNumber + "/" + item + ".jpg";
    }

    public static String getVideoPath(String scenesId, String contactNumber, int item) {
        return "/home/data/image/" + scenesId + "/" + contactNumber + "/" + item + ".mp4";
    }


    public static String detectLanguage(String message) {
        RetryTemplate retryTemplate = createRetryTemplate();
        try {
            return retryTemplate.execute(context -> {
                Environment env = SpringUtils.getBean(Environment.class);
                String url = env.getProperty("apiSevicePath.detect_language");
                // 构建完整URL
                String fullUrl = url + "?text=" + message;

                ResponseEntity<String> response = restTemplate.getForEntity(fullUrl, String.class);
                if (response == null) {
                    log.warn("Received null response, triggering retry");
                    throw new Exception("Response body is empty");
                }
                String body = response.getBody();
                if (body != null && body.startsWith("\"") && body.endsWith("\"")) {
                    body = body.substring(1, body.length() - 1);
                }
                if (StringUtils.isNull(body)) {
                    log.warn("Received empty body, triggering retry");
                    throw new Exception("Response body is empty");
                }
                log.info("detectLanguage body:" + body);
                return body;
            });
        } catch (Exception e) {
            log.error("detectLanguage 错误:" + e);
        }
        return null;
    }


    /**
     * 免回时间
     * 客服休息时间
     */
//    public static boolean isWithinTimeRange(String customerId) {
//        String keys = "persona:customer:" + customerId + ":work";
//        redisCache.getCacheObject(keys);
//        // 获取当前时间
//        LocalTime currentTime = LocalTime.now();
//        // 定义上班时间范围
//        LocalTime startWorkTime = LocalTime.of(4, 30);   // 早上9:00
//        LocalTime endWorkTime = LocalTime.of(11, 30);    // 下午17:00
//        // 判断是否在上班时间内
//        if (currentTime.isAfter(startWorkTime) && currentTime.isBefore(endWorkTime)) {
//            return true;
//        } else {
//            return false;
//        }
//    }
    public static String replaceReponeBody(String reponeBody) {
        // 对回复内容进行清理，移除多余的符号和换行符
        return reponeBody.replace("* ", "").replace("：", "").replace(":", "").replace("\n", "").replace("\\n", "").replace("]", "").replace("[", "").replace("[", "").replace("“", "").replace("”", "").replace("*", "").replace("她", "").trim();
    }

    public static String prefixesBody(String intentPrompt, String[] prefixes, String fansId) {
        try {
            String reponeBody = getChatIntent(intentPrompt, fansId);
            if (StringUtils.isNotEmpty(reponeBody)) {
                for (String prefix : prefixes) {
                    // 如果回复中包含某个前缀，则将该前缀之后的内容提取出来
                    if (reponeBody.contains(prefix)) {
                        String[] content = reponeBody.split(Pattern.quote(prefix));
                        if (content.length < 3) {
                            if (StringUtils.isNotNull(content[content.length - 1])) {
                                return content[content.length - 1];
                            }
                        } else {
                            if (StringUtils.isNotNull(content[1])) {
                                return content[1];
                            }
                        }
                    } else {
                        return reponeBody;
                    }
                }
            }
        } catch (Exception e) {
            log.error("prefixesBody Exception:" + intentPrompt);
        }
        return null;
    }

}
